#include <iostream>
// #include "newserver.c"

using namespace std;


class Gameboard
{
	private:
		bool undoPossible;
		bool redoPossible;
		char tempboard[10][10];
		char unboard[10][10];
		char reboard[10][10];
		char unstack[69][10][10];
		char restack[69][10][10];
		int uni;
		int rei;
		
		char piece;
		bool toggleDisplay;
		short numStar;
		bool first;

	public:
		server bob;
		char board[10][10];// nead to make fuctions to set and get board;
		void copy(char source[10][10], char destination[10][10]);
		void setup();
		void black();
		void white();
		void findAvailable(short row, short column);
		void flip(short row, short column);
		void showNextPos();
		bool move(int row, int column);
		bool move(int row, char column);
		void display();
		void showDisplay(bool a);
		char currentColor();
		void gameOver();
		void undo();
		void redo();
		void checkgameover();
		void Setpiece(char p);
		int count_num_moves();
		//int findpositions(char color);

};

void Gameboard:: redo()
{
	if(rei>=0)
	{
		//copy(board,unboard);
		uni++;
		for(int i=0; i<10; i++)
		{
			for(int j=0; j<10; j++)
			{
				unstack[uni][i][j]=board[i][j];
			}
		}
		for(int i=0; i<10; i++)
		{
			for(int j=0; j<10; j++)
			{
				board[i][j]=restack[rei][i][j];
			}
		}
		rei--;
		
		//copy(reboard, board);
	if(currentColor() == '@')
	{
		white();
	}
	else
	{
			if(currentColor() == 'O')
				black();
	}
		 undoPossible= true;
		 redoPossible= false;
	}
	else
		bob.server_send("redo not possible");

}
void Gameboard:: undo()
{
	
	
	if(uni>=0)
	{
		
		//copy(board,reboard); 
		rei++;
		for(int i=0; i<10; i++)
		{
			for(int j=0; j<10; j++)
			{
				restack[rei][i][j]=board[i][j];
			}
		}
		
		//copy(unboard, board);
		
		for(int i=0; i<10; i++)
		{
			for(int j=0; j<10; j++)
			{
				board[i][j]=unstack[uni][i][j];
			}
		}
		uni--;
		 if(piece == '@')
			white();
	
		 if(piece == 'O')
			black();
		 undoPossible= false;
		 redoPossible= true;

	}
	else
		bob.server_send("undo not possible");

}

void Gameboard:: copy(char source[10][10], char destination[10][10])
{
	for(short i=0; i<10; i++)
	{
		for(short j=0; j<10; j++)
		{
			destination[i][j] = source[i][j];
		}
	}
}

int Gameboard:: count_num_moves()
{
	int p = 0;

	for(int i=1; i<10; i++)
	{
		for(int j=1; j<10; j++)
		{
			if(board[i][j] == '*')
			{
				p++;
			}
		}
	}
	return p;

}


void Gameboard:: setup()
{
	black();
	
	uni=-1;
	rei=-1;
	//setup board to have z along the edges and _ inside
	for (int i=0; i<10; i++)
	{
		
		//border
		board[0][i] = 'z';
		board[i][0] = 'z';
		board[9][i] = 'z';
		board [i][9] = 'z';
		
		{
			for (int j=0; j<9; j++)
			{
				if(i>0 && j>0 && j<9 && i<9)
				{
					board[i][j] = '_';
				}
			}
		}
	}
	
	//initialize the middle 4
	board[4][4] = '@';
	board[4][5] = 'O';
	board[5][4] = 'O';
	board[5][5] = '@';
	
	
}

void Gameboard:: black()
{
	piece = '@';
}

void Gameboard:: white()
{
	piece = 'O';
}
void Gameboard:: Setpiece(char p)
{
	 if(p == 'O')
		white();
	
	else if(p == '@')
		black();
}

void Gameboard:: gameOver()
{
	char c;
	int totalBlack = 0;
	int totalWhite = 0;

	for(int i=0; i<10; i++)
	{
		for(int j=0; j<10; j++)
		{	
			if(board[i][j] == '@')
				totalBlack++;
			if(board[i][j] == 'O')
				totalWhite++;
		}
	}
	display();
	if(totalBlack > totalWhite)
		bob.server_send("BLACK WINS\n");
	else if(totalWhite > totalBlack)
		bob.server_send("WHITE WINS\n");
		
	else
		bob.server_send("TIE\n");
		
		char a[100];
		sprintf(a,"white has %d\n",totalWhite);
		bob.server_send(a);
		memset((char*)&a,0, sizeof(a));
		sprintf(a,"black has %d\n",totalBlack);
		bob.server_send(a);
		bob.server_send("\nTHE GAME HAS ENDED ENTER A LETTER TO EXIT ");
		
		
		string l = bob.server_recv();
		exit(0);
}

void Gameboard:: findAvailable(short row, short column)
{
	numStar = 0;
	char opp;
	short i;
	short j;
	if(piece == 'O')
		opp = '@';
	else if(piece == '@')
		opp = 'O';
		
		
	char nextcell = 'a';

	//TRAVERSE UP
	i = row-1;
	nextcell = tempboard[i][column];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = tempboard[--i][column];
			if(nextcell == '_')
			{
				tempboard[i][column] = '*';
				numStar++;
			}
		}
		else
		{
			break;
		}
	}
	
	//TRAVERSE UP-RIGHT
	i = row-1;
	j = column+1;
	nextcell = tempboard[i][j];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = tempboard[--i][++j];
			if(nextcell == '_')
			{
				tempboard[i][j] = '*';
				numStar++;
			}
		}
		else
		{
			break;
		}
	}
	
	//TRAVERSE RIGHT
	i = column+1;
	nextcell = tempboard[row][i];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = tempboard[row][++i];
			if(nextcell == '_')
			{
				tempboard[row][i] = '*';
				numStar++;
			}
		}
		else
		{
			break;
		}
	}
	
	//TRAVERSE DOWN-RIGHT
	i = row+1;
	j = column+1;
	nextcell = tempboard[i][j];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = tempboard[++i][++j];
			if(nextcell == '_')
			{
				tempboard[i][j] = '*';
				numStar++;
			}
		}
		else
		{
			break;
		}
	}
	
	//TRAVERSE DOWN
	i = row+1;
	nextcell = tempboard[i][column];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = tempboard[++i][column];
			if(nextcell == '_')
			{
				tempboard[i][column] = '*';
				numStar++;
			}
		}
		else
		{
			break;
		}
	}
	
	//TRAVERSE DOWN-LEFT
	i = row+1;
	j = column-1;
	nextcell = tempboard[i][j];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = tempboard[++i][--j];
			if(nextcell == '_')
			{
				tempboard[i][j] = '*';
				numStar++;
			}
		}
		else
		{
			break;
		}
	}
	
	
	//TRAVERSE LEFT
	i = column-1;
	nextcell = tempboard[row][i];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = tempboard[row][--i];
			if(nextcell == '_')
			{
				tempboard[row][i] = '*';
				numStar++;
			}
		}
		else
		{
			break;
		}
	}
	
	
	
	//TRAVERSE UP-LEFT
	i = row-1;
	j = column-1;
	nextcell = tempboard[i][j];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = tempboard[--i][--j];
			if(nextcell == '_')
			{
				tempboard[i][j] = '*';
				numStar++;
			}
		}
		else
		{
			break;
		}
	}
}

void Gameboard:: showNextPos()
{	
	if(numStar == 0)
		first = true;
	else
		first = false;

	copy(board, tempboard);
	
	//clear stars
	for(int i=0; i<10; i++)
	{
		for(int j=0; j<10; j++)
		{	
			if(tempboard[i][j] == '*')
			{
				tempboard[i][j] = '_';
			}
		}
	}

	//traverse board
	for(int i=0; i<10; i++)
	{
		for(int j=0; j<10; j++)
		{	
			//when piece found
			if(board[i][j] == currentColor())
			{
				//looking for opposite color then empty
				//fill that empty with *
				findAvailable(i,j);
			}
		}
	}

	copy(tempboard, board);
	checkgameover();

	
}
void Gameboard:: checkgameover()
{
int numEmpty=0;
int p=0;
for(int i=0; i<10; i++)
	{
		for(int j=0; j<10; j++)
		{
			if(board[i][j] == '_')
			{ 
				numEmpty++;
			}
			if(board[i][j] == '*')
			{ 
				p++;
			}
		}
	}
	if((p == 0 )&&( first == true) && numEmpty==0)
		gameOver();
	
}
bool Gameboard:: move(int row, char column)
{
	//if (toggleDisplay== true)
	//{
	//	display();
	//}
	int num_star=0;
	for(int i=0; i<10; i++)
	{
		for(int j=0; j<10; j++)
		{
			if(board[i][j]=='*')
			{
				num_star++;
			}
		}
	}


	
	if(num_star==0)
	{
		if(piece == '@')
		white();
	
	else if(piece == 'O')
		black();
	}
	if(num_star!=0)
	{
	// copy(board, unboard);
	
		
		
	
	int icolumn = 0;
	
	if(column == 'a')
		icolumn = 1;
	if(column == 'b')
		icolumn = 2;
	if(column == 'c')
		icolumn = 3;
	if(column == 'd')
		icolumn = 4;
	if(column == 'e')
		icolumn = 5;
	if(column == 'f')
		icolumn = 6;
	if(column == 'g')
		icolumn = 7;
	if(column == 'h')
		icolumn = 8;
	
	//only allow move if its an available move
	if(board[row][icolumn] != '*')
	{
		bob.server_send("Sorry that move is not availble\n");
	}
	else
	{
		uni++;
		for(int i=0; i<10; i++)
		{
			for(int j=0; j<10; j++)
			{
			unstack[uni][i][j]= board[i][j];
			}
		}
		board[row][icolumn] = piece;
		flip(row,icolumn);
		//undoPossible=true;
	}
	}
	
	

	return true;
}
bool Gameboard:: move(int row, int column)
{
	//if (toggleDisplay== true)
	//{
	//	display();
	//}
	int num_star=0;
	for(int i=0; i<10; i++)
	{
		for(int j=0; j<10; j++)
		{
			if(board[i][j]=='*')
			{
				num_star++;
			}
		}
	}


	
	if(num_star==0)
	{
		if(piece == '@')
		white();
	
	else if(piece == 'O')
		black();
	}
	if(num_star!=0)
	{
	copy(board, unboard);
	int icolumn = column;
	
	
	
	//only allow move if its an available move
	if(board[row][icolumn] != '*')
	{
		bob.server_send("Sorry that move is not availble\n");
	}
	else
	{
		board[row][icolumn] = piece;
		flip(row,icolumn);
	}
	}
	
	

	return true;
}

void Gameboard:: flip(short row, short column)
{
//	cout << "current color: " << currentColor() << endl;
	char opp;
	short i;
	short j;
	short k;
	if(piece == 'O')
		opp = '@';
	else if(piece == '@')
		opp = 'O';
		
		
	char nextcell = 'a';
	
	//TRAVERSE UP
	i = row-1;
	nextcell = board[i][column];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = board[--i][column];
			if(nextcell == currentColor())
			{
				//flip
				for(short k=i; k<row; k++)
					board[k][column] = currentColor();
				
				break;
			}
		}
		else	//incase of empty
		{
			break;
		}
	}
	
	//TRAVERSE LEFT
	i = column-1;
	nextcell = board[row][i];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = board[row][--i];
			if(nextcell == currentColor())
			{
				//flip
				for(short k=i; k<column; k++)
					board[row][k] = currentColor();
				
				break;
			}
		}
		else	//incase of empty
		{
			break;
		}
	}
	
	//TRAVERSE RIGHT
	i = column+1;
	nextcell = board[row][i];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = board[row][++i];
			if(nextcell == currentColor())
			{
				//flip
				for(short k=i; k>column; k--)
					board[row][k] = currentColor();
				
				break;
			}
		}
		else	//incase of empty
		{
			break;
		}
	}
	
	//TRAVERSE DOWN
	i = row+1;
	nextcell = board[i][column];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = board[++i][column];
			if(nextcell == currentColor())
			{
				//flip
				for(short k=i; k>row; k--)
					board[k][column] = currentColor();
				
				break;
			}
		}
		else	//incase of empty
		{
			break;
		}
	}
	
	//TRAVERSE UP-LEFT
	i = row-1;
	j = column-1;
	short l;
	nextcell = board[i][j];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = board[--i][--j];
			if(nextcell == currentColor())
			{
				//flip
				l = j;
				for(short k=i; k<row; k++)
				{
					board[k][l] = currentColor();
					l++;
				}
				break;
			}
		}
		else
		{
			break;
		}
	}
	
	//TRAVERSE UP-RIGHT
	i = row-1;
	j = column+1;
	nextcell = board[i][j];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = board[--i][++j];
			if(nextcell == currentColor())
			{
				//flip
				short l = j;
				for(short k=i; k<row; k++)
				{
					board[k][l] = currentColor();
					l--;
				}
				break;
			}
		}
		else
		{
			break;
		}
	}
	
	
	//TRAVERSE DOWN-RIGHT
	i = row+1;
	j = column+1;
	nextcell = board[i][j];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = board[++i][++j];
			if(nextcell == currentColor())
			{
				//flip
				short l = j;
				for(short k=i; k>row; k--)
				{
					board[k][l] = currentColor();
					l--;
				}
				break;
			}
		}
		else
		{
			break;
		}
	}
	
	//TRAVERSE DOWN-LEFT
	i = row+1;
	j = column-1;
	nextcell = board[i][j];
	while (nextcell != 'z')
	{
		if(nextcell == opp)
		{
			nextcell = board[++i][--j];
			if(nextcell == currentColor())
			{
				//flip
				short l = j;
				for(short k=i; k>row; k--)
				{
					board[k][l] = currentColor();
					l++;
				}
				break;
			}
		}
		else
		{
			break;
		}
	}
	
	
	 if(piece == '@')
		white();
	
	else if(piece == 'O')
		black();
	
}
void Gameboard:: display()
{
	char a[2];
	bob.server_send("  a b c d e f g h\n");
	for(int i=1; i<9; i++)
	{
		// cout << i << "|";
		sprintf(a,"%d|",i);
		bob.server_send(a);
		for(int j=1; j<9; j++)
		{
			// cout << board[i][j] << "|";
			sprintf(a,"%c|",board[i][j]);
			bob.server_send(a);
		}
		// cout << endl;
		bob.server_send("\n");
	}
}

void Gameboard:: showDisplay(bool a)
{
	toggleDisplay = a;
}

char Gameboard:: currentColor()
{
	return piece;
}

